﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YJKRevitBase.WinForm;
using YJKCoordinate;
using YJKRevitCurveDrag;
using YRevitJig;
using YJKTools.PublicPreViewer;
using YJKRevitView;
using YJKRevitPipeSetting.Forms;
using YJKRevitPipeSetting.LoadFamilys;
using YJKRevitPipeSetting.Utiltiy;

namespace YJKRevitPipeSetting
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class CmdSetPipe : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		Result IExternalCommand.Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			this.ui_app = commandData.Application;
			this.ui_doc = this.ui_app.ActiveUIDocument;
			this.m_doc = this.ui_doc.Document;
			if (Convert.ToInt32(commandData.Application.Application.VersionNumber) < 2014)
			{
				message = "此功能只在Revit2014及其以上版本可用。";
				return Autodesk.Revit.UI.Result.Failed;
			}
			CmdViewType types = (CmdViewType)11;
			if (SwitchView.SetUsableView(types, commandData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			if (CmdSetPipe._hWndRevit == null)
			{
				CmdSetPipe._hWndRevit = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			string appRootPath = YJKRevitPipeSetting.Utiltiy.Utiltiy.GetAppRootPath();
			string versionNumber = this.ui_app.Application.VersionNumber;
			string strUsePipeFamilyPath = appRootPath + "\\FamilyLib\\Family\\" + versionNumber + "\\PipeOccupied\\";
			string strUseEquipmentFamilyPath = appRootPath + "\\FamilyLib\\Family\\" + versionNumber + "\\EquipmentOccupied\\";
			StaticRescource.SetStrPathOutPut(Path.GetTempPath());
			StaticRescource.SetStrUsePipeFamilyPath(strUsePipeFamilyPath);
			StaticRescource.SetStrUseEquipmentFamilyPath(strUseEquipmentFamilyPath);
			if (!new LoadFamily(commandData).LoadPipeFamilys())
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			if (!new LoadFamilyPath(commandData).LoadEquipmentFamilys())
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			ViewAssist.ViewValidating(this.ui_doc.Document, this.ui_doc.ActiveView);
			return this.PlacePipeLoop(commandData);
		}

		private Result PlacePipeLoop(ExternalCommandData commandData)
		{
			PipeDrainMakerApplication pipeDrainMakerApplication = new PipeDrainMakerApplication(this.ui_app, this.m_doc);
			Result result;
			using (YJKRevitPipeSetting.Utiltiy.YRevitJigExtend hyjigExtend = new YJKRevitPipeSetting.Utiltiy.YRevitJigExtend(this.ui_doc))
			{
				SetPipeInfoForm setPipeInfoForm = null;
				try
				{
					setPipeInfoForm = new SetPipeInfoForm();
					setPipeInfoForm.Show(CmdSetPipe._hWndRevit);
				}
				catch (Exception)
				{
					if (setPipeInfoForm != null)
					{
						setPipeInfoForm.Close();
					}
					return Autodesk.Revit.UI.Result.Failed;
				}
				int wMsg = 7;
				CmdSetPipe.SendMessage(CmdSetPipe._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
				try
				{
					while (setPipeInfoForm.isExist)
					{
						if (setPipeInfoForm.m_CurrentOrder == "PipeOccupied")
						{
							if (this.getPointLoop(this.ui_doc, pipeDrainMakerApplication, hyjigExtend, setPipeInfoForm) != null || !setPipeInfoForm.BIsEndPipeOccupied)
							{
								ProcessBarForm processBarForm = new ProcessBarForm();
								processBarForm.Show();
								pipeDrainMakerApplication.MakeFamilies(processBarForm);
								pipeDrainMakerApplication.AddFamilies(processBarForm);
								pipeDrainMakerApplication.DeleteAllDetailCurves();
								processBarForm.Close();
								if (pipeDrainMakerApplication.GetEndPointNow() == null)
								{
									setPipeInfoForm.Close();
									break;
								}
							}
						}
						else if (setPipeInfoForm.m_CurrentOrder == "EquipmentOccupied")
						{
							if (setPipeInfoForm.curveInfoList == null || setPipeInfoForm.curveInfoList.Count == 0)
							{
								setPipeInfoForm.Refresh();
							}
							List<JigEdgeInfo> list = new List<JigEdgeInfo>();
							foreach (CurveInfo curveInfo in setPipeInfoForm.curveInfoList)
							{
								if (!(null == curveInfo.CurveObj))
								{
									JigEdgeInfo item = new JigEdgeInfo(curveInfo.CurveObj);
									list.Add(item);
								}
							}
							XYZ xyz = null;
							List<JigTextInfo> textInfos = new List<JigTextInfo>();
							if (!DragCurveJigInterface.GetInsertPosition(commandData, list, false, textInfos, false, setPipeInfoForm.m_TransVector, ref xyz))
							{
								if (setPipeInfoForm.IfBackGroundEsc)
								{
									continue;
								}
								setPipeInfoForm.Close();
							}
                            if (xyz != null && (int)this.AddFamily(setPipeInfoForm, xyz) == -1)
							{
								setPipeInfoForm.Close();
								break;
							}
						}
					}
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Exception ex)
				{
					try
					{
						setPipeInfoForm.Close();
					}
					catch (Exception)
					{
					}
					YJKMessageBox.Show(ex.Message);
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
			}
			return result;
		}

		private XYZ getPointLoop(UIDocument ui_doc, PipeDrainMakerApplication thisApplicantion, YJKRevitPipeSetting.Utiltiy.YRevitJigExtend tempYRevitJigExtend, SetPipeInfoForm tempForm)
		{
			XYZ xyz = null;
			new XYZ();
			new List<List<XYZ>>();
			thisApplicantion.ResetEndPointNow();
			do
			{
				Dictionary<int, double> parametersByName = tempForm.GetParametersByName();
				tempYRevitJigExtend.SetWidth(parametersByName[0]);
				tempYRevitJigExtend.SetPos(parametersByName[3]);
				xyz = null;
				if (thisApplicantion.GetEndPointNow() == null)
				{
					xyz = tempYRevitJigExtend.PickSrartPointEX("请选择一点，ESC结束");
				}
				else
				{
					xyz = tempYRevitJigExtend.PickEndPointEX(thisApplicantion.GetEndPointNow(), "请选择一点，ESC结束", false);
				}
				if (xyz != null)
				{
					OnePipeInputDataPacker input;
					try
					{
						input = new OnePipeInputDataPacker(xyz, tempForm.GetCornerKind(), tempForm.GetParametersByName(), tempForm.GetFamilyFileIndex());
					}
					catch (CornerMakerException ex)
					{
						if (ex.Message.Equals(StaticRescource.StrError_WrongParameter))
						{
							YJKMessageBox.Show(StaticRescource.StrMessage_WrongParameter);
							goto IL_176;
						}
						throw ex;
					}
					thisApplicantion.AddOnePoint(input);
				}
				else
				{
					if (tempForm.IfBackGroundEsc)
					{
						break;
					}
					if (DrainMakerApplication.UseMessageTag)
					{
						thisApplicantion.AddOnePoint(null);
					}
					else
					{
						tempForm.Visible = false;
						XYZ[] array = new XYZ[2];
						for (int i = 0; i <= 1; i++)
						{
							try
							{
								if (i == 0)
								{
									array[i] = ui_doc.Selection.PickPoint("请选一点");
								}
								else
								{
									array[i] = tempYRevitJigExtend.PickEndPointEX(array[0], "请选另一点", true);
								}
							}
							catch (Exception)
							{
								array[i] = null;
								break;
							}
						}
						if (array[0] != null && array[1] != null && !array[0].IsAlmostEqualTo(array[1]))
						{
							array[0].DistanceTo(array[1]);
						}
						else
						{
							YJKMessageBox.Show("量取有误");
						}
						tempForm.Visible = true;
						DrainMakerApplication.UseMessageTag = true;
						xyz = XYZ.Zero;
					}
				}
				IL_176:;
			}
			while (xyz != null);
			return xyz;
		}

		private Result AddFamily(SetPipeInfoForm currentForm, XYZ xyz)
		{
			Transaction transaction = new Transaction(this.m_doc, "addFamily");
			transaction.Start();
			string text = StaticRescource.StrArrayUseEquipmentFamilyNames[currentForm.EquipmentFamilyIndex];
			FamilySymbol familySymbol = null;
			if (!this.ifHasUseFamily(text, out familySymbol))
			{
				string text2 = StaticRescource.StrUsePipeFamilyPath + text + StaticRescource.StrRfa;
                this.m_doc.LoadFamilySymbol(text2, text, out familySymbol);
			}
			if (familySymbol != null)
			{
				familySymbol.Activate();
				XYZ xyz2 = this.TransformInsertPt(currentForm, new XYZ(xyz.X, xyz.Y, this.m_doc.ActiveView.GenLevel.Elevation));
				if (xyz2 == null)
				{
					YJKMessageBox.Show("无法布置，请重新检查占位参数设置!");
					transaction.Commit();
					return Autodesk.Revit.UI.Result.Failed;
				}
				FamilyInstance input = this.m_doc.Create.NewFamilyInstance(xyz2, familySymbol, this.m_doc.ActiveView.GenLevel, (Autodesk.Revit.DB.Structure.StructuralType)0);
				input.GetParametersByName(StaticRescource.StrLength).Single<Parameter>().Set(currentForm.dLenght);
				input.GetParametersByName(StaticRescource.StrWidth).Single<Parameter>().Set(currentForm.dWidth);
				input.GetParametersByName(StaticRescource.Strheight).Single<Parameter>().Set(currentForm.dHeight);
			}
			transaction.Commit();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private XYZ TransformInsertPt(SetPipeInfoForm currentForm, XYZ pt)
		{
			XYZ result = new XYZ();
			if (currentForm.dWidth.ToString() == "0" || currentForm.dHeight.ToString() == "0" || currentForm.dLenght.ToString() == "0")
			{
				return null;
			}
			if (currentForm.dWidth > 0.0 && currentForm.dHeight > 0.0)
			{
				double num = currentForm.dLenght / 2.0;
				double num2 = currentForm.dWidth / 2.0;
				switch (currentForm.index)
				{
				case 0:
					result = pt;
					break;
				case 1:
					result = new XYZ(pt.X, pt.Y + num2 * 2.0, 0.0);
					break;
				case 2:
					result = new XYZ(pt.X - num * 2.0, pt.Y + num2 * 2.0, 0.0);
					break;
				case 3:
					result = new XYZ(pt.X - num * 2.0, pt.Y, 0.0);
					break;
				case 4:
					result = new XYZ(pt.X - num, pt.Y + num2, 0.0);
					break;
				}
			}
			return result;
		}

		private bool ifHasUseFamily(string familyName, out FamilySymbol outFamilySymobl)
		{
			outFamilySymobl = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfCategory(BuiltInCategory.OST_MassTags_Obsolete_IdInWrongRange).WhereElementIsElementType();
			foreach (Element element in (filteredElementCollector.ToElements() as List<Element>))
			{
				FamilySymbol familySymbol = element as FamilySymbol;
				if (familySymbol.Family.Name == familyName)
				{
					outFamilySymobl = familySymbol;
					return true;
				}
			}
			if (outFamilySymobl == null)
			{
				YJKMessageBox.Show("读取族失败");
			}
			outFamilySymobl.Activate();
			return true;
		}

		private UIApplication ui_app;

		private UIDocument ui_doc;

		private Document m_doc;

		public static WindowHandle _hWndRevit;
	}
}
